package spinal_loongarch_core132

import spinal.core._
import spinal.lib._

class CsrWb extends Bundle{
    val va   :UInt = LISA.GPR
    val pc   :UInt = LISA.GPR 
    val ex   :Bool = Bool()
    val ecode:UInt = LISA.Ex.Code
    val esubc:UInt = LISA.Ex.Subc
    val ertn :Bool = Bool()
    val ll   :Bool = Bool()
    def isRefill = ex && ecode === LISA.Ex.TLBR.code
    def isMemEx  = ex && LISA.Ex.isMem(ecode)
    def isTlbEx  = ex && LISA.Ex.isTlb(ecode)
    def gen_cancel(csr:Csr,exbus:CoreCancel){
        exbus.cancel := ex || ertn
        when(ex){
            exbus.target := Mux(isRefill,csr.tlbrentry.pa,csr.eentry.va) << 6
        }.otherwise{
            exbus.target := csr.era.pc
        }
    }
}
class StageWb extends Component{
    val io = new Bundle{
        val ic:PipeCtrl = slave(new PipeCtrl)
        val idat:SDatWb = in(new SDatWb)
        val fw:Forwarding = out(new Forwarding)
        val grw:RFWrite = out(new RFWrite)
        val tocsr:CsrWb = out(new CsrWb)
        val debug:CoreDebug = out(new CoreDebug)
    }
    io.fw.valid := io.ic.valid
    io.fw.grwr  := io.idat.grwr
    io.fw.dest  := io.idat.dest
    io.fw.block := False
    io.fw.value := io.idat.value
    io.ic.allow := True
    io.ic.empty := True

    val grwr:Bool = io.ic.valid && io.idat.grwr && !io.ic.ex
    io.grw.en   := grwr
    io.grw.addr := io.idat.dest
    io.grw.data := io.idat.value
   
    io.tocsr.va := io.idat.va
    io.tocsr.pc := io.idat.pc
    io.tocsr.ex := io.ic.ex
    io.tocsr.ecode := io.idat.ecode
    io.tocsr.esubc := io.idat.esubc
    io.tocsr.ll    := io.ic.valid && Instructions.isInst(io.idat.inst, "LL.W")
    io.tocsr.ertn  := io.ic.valid && io.idat.itype.is_ertn

    io.debug.pc       := io.idat.pc
    io.debug.rf_wen   := Mux(grwr, U"1111", U(0))
    io.debug.rf_wnum  := io.idat.dest
    io.debug.rf_wdata := io.idat.value
}
